package com.symaster.common.swing.list;

import com.symaster.common.swing.util.ThreadPoolUtil;

import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.*;

/**
 * swing自定义列表
 *
 * @author MGZC
 * @time 2021/8/24 21:52
 */
public class SwingListPanel extends JPanel {

    private final Boolean autoWidth;
    private final List<SwingListAbs> list = new ArrayList<>();
    private final Map<String, SwingListAbs> uuidMap = new HashMap<>();
    // 列表长度发生改变事件
    private final Set<ListLengthAlterListener> listLengthAlterListeners = new HashSet<>();
    // 列表选择元素事件列表
    private final Set<SelectElementListener> selectElementListeners = new HashSet<>();
    // 自定义事件
    private final Set<OtherListener> otherListeners = new HashSet<>();
    private final Integer itemWidth;
    private final Integer itemHeight;
    private final Integer hgap;
    private final Integer vgap;
    private final Color backgroundColor;
    // 当前选择的元素uuid
    private String selectElementUUID;

    public SwingListPanel(Integer itemWidth, Integer itemHeight) {
        this.itemWidth = itemWidth;
        this.itemHeight = itemHeight;
        hgap = 5;
        vgap = 5;
        backgroundColor = new Color(255, 255, 255);
        this.autoWidth = true;
        initLayout();
    }

    public SwingListPanel(Integer itemWidth, Integer itemHeight, Color backgroundColor) {
        this.itemWidth = itemWidth;
        this.itemHeight = itemHeight;
        this.backgroundColor = backgroundColor;
        hgap = 5;
        vgap = 5;
        this.autoWidth = true;
        initLayout();
    }

    public SwingListPanel(Integer itemWidth, Integer itemHeight, Color backgroundColor, Integer hgap, Integer vgap) {
        this.itemWidth = itemWidth;
        this.itemHeight = itemHeight;
        this.backgroundColor = backgroundColor;
        this.hgap = hgap;
        this.vgap = vgap;
        this.autoWidth = true;
        initLayout();
    }

    public SwingListPanel(Integer itemWidth, Integer itemHeight, Color backgroundColor, Integer hgap, Integer vgap, Boolean autoWidth) {
        this.itemWidth = itemWidth;
        this.itemHeight = itemHeight;
        this.backgroundColor = backgroundColor;
        this.hgap = hgap;
        this.vgap = vgap;
        this.autoWidth = autoWidth;
        initLayout();
    }

    /**
     * 通过索引删除元素
     */
    public void delete(int index) {
        SwingListAbs remove = list.remove(index);
        this.remove(index);
        uuidMap.remove(remove.getUuid());
        repaint();
        listLengthAlterListener();
    }

    /**
     * 通过唯一id 删除元素
     */
    public void delete(String uuid) {
        SwingListAbs swingListAbs = uuidMap.get(uuid);
        if (swingListAbs == null) {
            System.err.printf("[ERROR] SwingListPanel.delete(String uuid) 此%s uuid不存在%n", uuid);
            return;
        }
        int index = swingListAbs.getIndex();
        delete(index);
        repaint();
        listLengthAlterListener();
    }

    /**
     * 清空所有元素
     */
    public void clear() {
        list.clear();
        uuidMap.clear();
        this.removeAll();
        repaint();
        listLengthAlterListener();
    }

    /**
     * 添加元素
     */
    public void put(SwingListAbs panel) {
        setItemLayout(panel);
        list.add(panel);
        this.add(panel);
        uuidMap.put(panel.getUuid(), panel);
        repaint();
        listLengthAlterListener();
    }

    public SwingListAbs get(String uuid) {
        return uuidMap.get(uuid);
    }

    /**
     * 选择元素
     */
    public void select(String uuid) {
        if (this.selectElementUUID == null) {
            this.selectElementUUID = uuid;
            SwingListAbs swingListAbs = this.uuidMap.get(uuid);
            swingListAbs.selectListener();
            selectElementListener();
            return;
        }

        if (this.selectElementUUID.equals(uuid)) {
            return;
        }

        SwingListAbs swingListAbs = this.uuidMap.get(selectElementUUID);
        swingListAbs.oldSelectListener();
        this.selectElementUUID = uuid;

        SwingListAbs swingListAbs1 = this.uuidMap.get(uuid);
        swingListAbs1.selectListener();
        selectElementListener();
    }

    /**
     * 添加元素
     */
    public void put(int index, SwingListAbs panel) {
        setItemLayout(panel);
        list.add(index, panel);
        this.add(panel, index);
        repaint();
        listLengthAlterListener();
    }

    /**
     * 返回长度
     */
    public int length() {
        return list.size();
    }

    /**
     * 设置元素布局
     */
    private void setItemLayout(SwingListAbs slp) {
        slp.setPreferredSize(new Dimension(itemWidth, itemHeight));
    }

    /**
     * 初始化布局
     */
    public void initLayout() {
        setLayout(new FlowLayout(FlowLayout.CENTER, hgap, vgap));
        setBackground(backgroundColor);
    }

    /**
     * 返回所有元素
     */
    public List<SwingListAbs> getList() {
        return list;
    }

    /**
     * 添加长度监听事件
     */
    public void addListLengthAlterListener(ListLengthAlterListener listener) {
        listLengthAlterListeners.add(listener);
    }

    /**
     * 删除长度监听事件
     */
    public void removeListLengthAlterListener(ListLengthAlterListener listener) {
        listLengthAlterListeners.remove(listener);
    }

    /**
     * 添加选择元素事件
     */
    public void addSelectElementListener(SelectElementListener listener) {
        selectElementListeners.add(listener);
    }

    /**
     * 移除选择元素事件
     */
    public void removeSelectElementListener(SelectElementListener listener) {
        selectElementListeners.remove(listener);
    }

    /**
     * 添加自定义事件
     */
    public void addOtherListener(OtherListener listener) {
        otherListeners.add(listener);
    }

    /**
     * 移除自定义事件
     */
    public void removeOtherListener(OtherListener listener) {
        otherListeners.remove(listener);
    }

    /**
     * 长度发生改变事件
     */
    public void listLengthAlterListener() {
        if (listLengthAlterListeners != null && listLengthAlterListeners.size() != 0) {
            for (ListLengthAlterListener ll : listLengthAlterListeners) {
                ll.handle(length());
            }
        }
        if (list == null || list.size() == 0) {
            return;
        }


        for (SwingListAbs swingListAbs : list) {
            ThreadPoolUtil.execute(() -> swingListAbs.listLengthAlterListener(length()));
        }
    }

    /**
     * 选择元素事件
     */
    public void selectElementListener() {
        if (selectElementListeners == null || selectElementListeners.size() == 0) {
            return;
        }
        SwingListAbs swingListAbs = uuidMap.get(selectElementUUID);
        ThreadPoolUtil.execute(() -> {
            for (SelectElementListener selectElementListener : selectElementListeners) {
                selectElementListener.handle(swingListAbs);
            }
        });
    }

    /**
     * 调用自定义事件
     */
    public void otherListener(SwingListAbs swingListAbs) {
        if (otherListeners == null || otherListeners.size() == 0) {
            return;
        }
        ThreadPoolUtil.execute(() -> {
            for (OtherListener otherListener : otherListeners) {
                otherListener.handle(swingListAbs);
            }
        });
    }

    @Override
    public void repaint() {
        super.repaint();

        if (list == null) {
            return;
        }

        if (list.size() == 0) {
            setPreferredSize(new Dimension(itemWidth + hgap * 2, 0));
            return;
        }

        setPreferredSize(new Dimension(itemWidth + hgap * 2, (itemHeight + vgap) * (list.size() + 1)));
    }

    /**
     * 长度发生改变事件调用
     */
    public interface ListLengthAlterListener {
        void handle(int newLen);
    }

    /**
     * 列表选择事件
     */
    public interface SelectElementListener {
        void handle(SwingListAbs select);
    }

    /**
     * 自定义事件
     */
    public interface OtherListener {
        void handle(SwingListAbs o);
    }
}
